/**
 * ***************************************************************************** Copyright (c) 2005,
 * 2006 Subclipse project and others. All rights reserved. This program and the accompanying
 * materials are made available under the terms of the Eclipse Public License v1.0 which accompanies
 * this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
 *
 * <p>Contributors: Subclipse project committers - initial API and implementation
 * ****************************************************************************
 */
package org.tigris.subversion.subclipse.ui.dialogs;

import org.eclipse.core.resources.IResource;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.tigris.subversion.subclipse.core.SVNException;
import org.tigris.subversion.subclipse.ui.IHelpContextIds;
import org.tigris.subversion.subclipse.ui.Policy;
import org.tigris.subversion.subclipse.ui.SVNUIPlugin;
import org.tigris.subversion.subclipse.ui.comments.CommitCommentArea;
import org.tigris.subversion.subclipse.ui.settings.CommentProperties;
import org.tigris.subversion.subclipse.ui.settings.ProjectProperties;
import org.tigris.subversion.subclipse.ui.util.LinkList;
import org.tigris.subversion.svnclientadapter.SVNRevision;

public class SetCommitPropertiesDialog extends SubclipseTrayDialog {

  private CommitCommentArea commitCommentArea;
  private ProjectProperties projectProperties;
  private Text issueText;
  private Text committerText;
  private String issue;
  private String author;
  private IDialogSettings settings;
  private SVNRevision revision;

  private Button okButton;
  private CommentProperties commentProperties;

  public SetCommitPropertiesDialog(
      Shell parentShell,
      SVNRevision revision,
      IResource theResource,
      ProjectProperties projectProperties) {
    super(parentShell);
    int shellStyle = getShellStyle();
    setShellStyle(shellStyle | SWT.RESIZE);

    try {
      if (theResource != null)
        commentProperties = CommentProperties.getCommentProperties(theResource);
    } catch (SVNException e1) {
      // So what!
    }

    commitCommentArea = new CommitCommentArea(this, null, commentProperties);
    if ((commentProperties != null) && (commentProperties.getMinimumLogMessageSize() != 0)) {
      ModifyListener modifyListener =
          new ModifyListener() {
            public void modifyText(ModifyEvent e) {
              okButton.setEnabled(
                  commitCommentArea.getComment().trim().length()
                      >= commentProperties.getMinimumLogMessageSize());
            }
          };
      commitCommentArea.setModifyListener(modifyListener);
    }
    this.revision = revision;
    this.projectProperties = projectProperties;
    settings = SVNUIPlugin.getPlugin().getDialogSettings();
  }

  /*
   * @see Dialog#createDialogArea(Composite)
   */
  protected Control createDialogArea(Composite parent) {

    getShell()
        .setText(
            Policy.bind(
                "SetCommitPropertiesDialog.revisionNumber",
                revision.toString())); // $NON-NLS-1$//$NON-NLS-2$
    Composite composite = new Composite(parent, SWT.NULL);
    composite.setLayout(new GridLayout());
    composite.setLayoutData(new GridData(GridData.FILL_BOTH));

    if (projectProperties != null) {
      if (projectProperties.getMessage() != null) {
        addBugtrackingArea(composite);
      }
    }

    commitCommentArea.createArea(composite);
    commitCommentArea.addPropertyChangeListener(
        new IPropertyChangeListener() {
          public void propertyChange(PropertyChangeEvent event) {
            if (event.getProperty() == CommitCommentArea.OK_REQUESTED) okPressed();
          }
        });
    addCommitterName(composite);
    if (author != null) committerText.setText(author);

    FocusListener focusListener =
        new FocusAdapter() {
          public void focusGained(FocusEvent e) {
            ((Text) e.getSource()).selectAll();
          }

          public void focusLost(FocusEvent e) {
            ((Text) e.getSource()).setText(((Text) e.getSource()).getText());
          }
        };
    committerText.addFocusListener(focusListener);
    if (issueText != null) issueText.addFocusListener(focusListener);

    // set F1 help
    PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.CHANGE_REVPROPS);

    return composite;
  }

  private void addBugtrackingArea(Composite composite) {
    Composite bugtrackingComposite = new Composite(composite, SWT.NULL);
    GridLayout bugtrackingLayout = new GridLayout();
    bugtrackingLayout.numColumns = 2;
    bugtrackingComposite.setLayout(bugtrackingLayout);

    Label label = new Label(bugtrackingComposite, SWT.NONE);
    label.setText(projectProperties.getLabel());
    issueText = new Text(bugtrackingComposite, SWT.BORDER);
    GridData data = new GridData();
    data.widthHint = 150;
    issueText.setLayoutData(data);
  }

  private void addCommitterName(Composite composite) {
    Composite committerComposite = new Composite(composite, SWT.NULL);
    GridLayout committerLayout = new GridLayout();
    committerLayout.numColumns = 2;
    committerComposite.setLayout(committerLayout);

    Label label = new Label(committerComposite, SWT.NONE);
    label.setText(Policy.bind("SetCommitPropertiesDialog.user"));
    committerText = new Text(committerComposite, SWT.BORDER);
    GridData data = new GridData();
    data.widthHint = 150;
    committerText.setLayoutData(data);
  }

  protected void okPressed() {
    saveLocation();
    if (confirmUserData() == false) {
      return;
    }
    if (committerText.getText().trim().length() == 0) {
      MessageDialog.openError(
          getShell(),
          Policy.bind("SetCommitPropertiesDialog.title"),
          Policy.bind("SetCommitPropertiesDialog.noAuthor")); // $NON-NLS-1$ //$NON-NLS-2$
      committerText.selectAll();
      committerText.setFocus();
      return; //$NON-NLS-1$
    }
    author = committerText.getText().trim();

    super.okPressed();
  }

  private boolean confirmUserData() {

    if (projectProperties != null) {
      int issueCount = 0;
      if (projectProperties.getMessage() != null) {

        issue = issueText.getText().trim();
        if (issue.length() > 0) {
          String issueError = projectProperties.validateIssue(issue);
          if (issueError != null) {
            MessageDialog.openError(
                getShell(),
                Policy.bind("SetCommitPropertiesDialog.title"),
                issueError); //$NON-NLS-1$
            issueText.selectAll();
            issueText.setFocus();
            return false;
          } else {
            issueCount++;
          }
        }
      }
      if (projectProperties.getLogregex() != null) {

        try {
          LinkList linkList = projectProperties.getLinkList(commitCommentArea.getComment());
          String[] urls = linkList.getUrls();
          issueCount += urls.length;

        } catch (Exception e) {
          handle(e, null, null);
        }
      }
      if (projectProperties.isWarnIfNoIssue()) {

        if (issueCount == 0) {
          if ((projectProperties.getMessage() != null)
              && (projectProperties.getLogregex() == null)) {
            if (!MessageDialog.openQuestion(
                getShell(),
                Policy.bind("SetCommitPropertiesDialog.title"),
                Policy.bind(
                    "SetCommitPropertiesDialog.0",
                    projectProperties.getLabel()))) { // $NON-NLS-1$ //$NON-NLS-2$
              issueText.setFocus();
              return false; //$NON-NLS-1$
            }
          } else if ((projectProperties.getMessage() == null)
              && (projectProperties.getLogregex() != null)) {
            if (!MessageDialog.openQuestion(
                getShell(),
                Policy.bind("SetCommitPropertiesDialog.title"),
                Policy.bind(
                    "SetCommitPropertiesDialog.1",
                    projectProperties.getLabel()))) { // $NON-NLS-1$ //$NON-NLS-2$
              commitCommentArea.setFocus();
              return false; //$NON-NLS-1$
            }
          } else if ((projectProperties.getMessage() != null)
              && (projectProperties.getLogregex() != null)) {
            if (!MessageDialog.openQuestion(
                getShell(),
                Policy.bind("SetCommitPropertiesDialog.title"),
                Policy.bind(
                    "SetCommitPropertiesDialog.2",
                    projectProperties.getLabel()))) { // $NON-NLS-1$ //$NON-NLS-2$
              commitCommentArea.setFocus();
              return false; //$NON-NLS-1$
            }
          }
        }
      }
    }
    return true;
  }

  protected void cancelPressed() {
    saveLocation();
    super.cancelPressed();
  }

  private void saveLocation() {
    int x = getShell().getLocation().x;
    int y = getShell().getLocation().y;
    settings.put("SetCommitPropertiesDialog.location.x", x); // $NON-NLS-1$
    settings.put("SetCommitPropertiesDialog.location.y", y); // $NON-NLS-1$
    x = getShell().getSize().x;
    y = getShell().getSize().y;
    settings.put("SetCommitPropertiesDialog.size.x", x); // $NON-NLS-1$
    settings.put("SetCommitPropertiesDialog.size.y", y); // $NON-NLS-1$
  }

  protected Point getInitialLocation(Point initialSize) {
    try {
      int x = settings.getInt("SetCommitPropertiesDialog.location.x"); // $NON-NLS-1$
      int y = settings.getInt("SetCommitPropertiesDialog.location.y"); // $NON-NLS-1$
      return new Point(x, y);
    } catch (NumberFormatException e) {
    }
    return super.getInitialLocation(initialSize);
  }

  protected Point getInitialSize() {
    try {
      int x = settings.getInt("SetCommitPropertiesDialog.size.x"); // $NON-NLS-1$
      int y = settings.getInt("SetCommitPropertiesDialog.size.y"); // $NON-NLS-1$
      return new Point(x, y);
    } catch (NumberFormatException e) {
    }
    return super.getInitialSize();
  }

  /**
   * Returns the comment.
   *
   * @return String
   */
  public String getComment() {
    String comment;
    if ((projectProperties != null) && (issue != null) && (issue.length() > 0)) {
      if (projectProperties.isAppend())
        comment =
            commitCommentArea.getComment()
                + "\n"
                + projectProperties.getResolvedMessage(issue)
                + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
      else
        comment =
            projectProperties.getResolvedMessage(issue)
                + "\n"
                + commitCommentArea.getComment(); // $NON-NLS-1$
    } else comment = commitCommentArea.getComment();
    commitCommentArea.addComment(commitCommentArea.getComment());
    return comment;
  }

  protected Button createButton(Composite parent, int id, String label, boolean defaultButton) {
    Button button = super.createButton(parent, id, label, defaultButton);
    if (id == IDialogConstants.OK_ID) {
      okButton = button;
      if ((commentProperties != null) && (commentProperties.getMinimumLogMessageSize() != 0)) {
        okButton.setEnabled(false);
      }
    }
    return button;
  }

  protected static final int LABEL_WIDTH_HINT = 400;

  protected Label createWrappingLabel(Composite parent) {
    Label label = new Label(parent, SWT.LEFT | SWT.WRAP);
    GridData data = new GridData();
    data.horizontalSpan = 1;
    data.horizontalAlignment = GridData.FILL;
    data.horizontalIndent = 0;
    data.grabExcessHorizontalSpace = true;
    data.widthHint = LABEL_WIDTH_HINT;
    label.setLayoutData(data);
    return label;
  }

  public void setOldComment(String comment) {
    commitCommentArea.setProposedComment(comment);
  }

  public void setOldAuthor(String oldAuthor) {
    this.author = oldAuthor;
  }

  public String getAuthor() {
    return author;
  }

  protected void handle(Exception exception, String title, String message) {
    SVNUIPlugin.openError(
        getShell(), title, message, exception, SVNUIPlugin.LOG_NONTEAM_EXCEPTIONS);
  }
}
